package controllers

import (
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"github.com/gogf/gf/os/glog"
	"github.com/gogf/gf/util/gconv"
	"io"
	"mdblog/models"
	"mdblog/models/blog"
	"os"
	"path"
	"time"
)

type CreateClassifyRequest struct {
	Name     string
	Key      string
	Describe string
}

func (request *CreateClassifyRequest) Do() error {
	return blog.CreateBlogClassify(request.Name, request.Key, request.Describe)
}

type PaginatorClassifyRequest struct {
	Limit int
	Page  int
}

func (request *PaginatorClassifyRequest) Do() ([]*blog.Classify, error) {
	return blog.GetBlogClassifyPaginator(request.Limit, request.Page)
}

type QueryClassifyAllRequest struct{}

func (request *QueryClassifyAllRequest) Do() ([]*blog.Classify, error) {
	return blog.GetAllBlogClassify()
}

type AllTargetsRequest struct{}

func (request *AllTargetsRequest) Do() ([]blog.Target, error) {
	return blog.GetAllArticleTargets()
}

type PaginatorTargetsRequest struct {
	Limit int
	Page  int
}

func (request *PaginatorTargetsRequest) Do() ([]blog.Target, error) {
	return blog.GetArticleTargetPaginator(request.Limit, request.Page)
}

type CreateTargetsRequest struct {
	Name     string `json:"name"`
	Classify string `json:"classify"`
}

func (request *CreateTargetsRequest) Do() error {
	classify, err := blog.GetBlogClassify(gconv.Int(request.Classify))
	if err != nil {
		return err
	}
	return blog.CreateArticleTarget(request.Name, classify)
}

type ClassifyTargetsQueryRequest struct {
	Classify string `json:"classify"`
}

func (request *ClassifyTargetsQueryRequest) Do() (all []blog.Target, err error) {
	classify, err := blog.GetBlogClassify(gconv.Int(request.Classify))
	if err != nil {
		return
	}
	return blog.GetClassifyTarget(classify)
}

type ArticleCreateRequest struct {
	Title     string `json:"title"`
	Targets   string `json:"targets"`
	Content   string `json:"content"`
	Introduce string `json:"introduce"`
	Recommend string `json:"recommend"`
	Comment   string `json:"comment"`
	Classify  string `json:"classify"`
}

func (request ArticleCreateRequest) Do() error {
	glog.Debug(request)
	classify, err := blog.GetBlogClassify(gconv.Int(request.Classify))
	if err != nil {
		return err
	}
	err = blog.CreateBlogArticle(request.Title, request.Targets, request.Introduce, request.Content, &classify)
	return err
}

type ArticleUpdateRequest struct {
	Id      int    `json:"id"`
	Title   string `json:"title"`
	Content string `json:"content"`
}

func (request ArticleUpdateRequest) Do() error {
	return blog.UpdateBlogArticle(request.Id, request.Title, request.Content)
}

type ArticleQueryPaginatorRequest struct {
	Limit int
	Page  int
}

func (request ArticleQueryPaginatorRequest) Do() ([]blog.Article, int64, error) {
	articles, total, err := blog.GetArticlesPaginator(request.Limit, request.Page)
	return articles, total, err
}

type SiteConfigsPaginatorRequest struct {
	Limit int
	Page  int
}

func (request SiteConfigsPaginatorRequest) Do() ([]models.Config, int64, error) {
	return models.GetConfigsPaginator(request.Limit, request.Page)
}

type SiteConfigCreateRequest struct {
	Key   string `json:"key"`
	Value string `json:"value"`
	Desc  string `json:"desc"`
}

func (request SiteConfigCreateRequest) Do() error {
	return models.CreateConfig(request.Key, request.Value, request.Desc)
}

type SiteConfigUpdateRequest struct {
	Key   string `json:"key"`
	Value string `json:"value"`
	Desc  string `json:"desc"`
}

func (request SiteConfigUpdateRequest) Do() error {
	config, err := models.GetConfigObjFromKey(request.Key)
	if err != nil {
		return err
	}
	config.Value = request.Value
	config.Desc = request.Desc
	return config.Save()
}

type ResourcePaginatorRequest struct {
	Limit int `json:"limit"`
	Page  int `json:"page"`
}

func (request ResourcePaginatorRequest) Do() ([]blog.Resources, int64, error) {
	return blog.GetResources(request.Limit, request.Page)
}

type ResourceUpdateRequest struct{}

func (request ResourceUpdateRequest) Do(o *BlogAdminApiController) (string, error) {
	f, h, err := o.GetFile("editormd-image-file")
	defer f.Close()

	if err != nil {
		return "", err
	}
	if path_, err := models.GetOneConfig("UploadPath"); err != nil {
		return "", err
	} else {
		m := md5.New()
		io.Copy(m, f)
		fileMd5 := hex.EncodeToString(m.Sum(nil))
		if blog.CheckResourceMd5(fileMd5) {
			resource, err := blog.GetResourceFromMd5(fileMd5)
			if err != nil {
				return "", err
			}
			return fmt.Sprintf("/resource/%s", resource.Md5), err
		}

		ext := path.Ext(h.Filename)
		datePath := time.Now().Format("2006/01/02")
		savePath := path.Join(path_, datePath)
		if _, err := os.Stat(savePath); err != nil {
			if os.IsNotExist(err) {
				err = os.MkdirAll(savePath, 0755)
				if err != nil {
					return "", err
				}
			}
		}
		filename := path.Join(savePath, fmt.Sprintf("%s%s", fileMd5, ext))
		err = blog.CreateResource(h.Filename, fileMd5, filename, h.Size, ext)
		if err != nil {
			return "", err
		}
		return fmt.Sprintf("/resource/%s", fileMd5), o.SaveToFile("editormd-image-file", filename)
	}
}

type RemoveResourceRequest struct {
	Id int `json:"id"`
}

func (request RemoveResourceRequest) Do() error {
	return blog.DeleteResourceFromId(request.Id)
}

type ArticleDeleteRequest struct {
	Id int
}

func (request ArticleDeleteRequest) Do() error {
	return blog.DeleteArticle(request.Id)
}

type NoticePaginatorRequest struct {
	Limit int `json:"limit"`
	Page  int `json:"page"`
}

func (request NoticePaginatorRequest) Do() ([]blog.Notice, int64, error) {
	return blog.GetNoticePaginator(request.Limit, request.Page)
}

type CreateNoticeRequest struct {
	Title   string `json:"title"`
	StartAt string `json:"start_at"`
	EndAt   string `json:"end_at"`
	Content string `json:"content"`
}

func (request CreateNoticeRequest) Do() error {
	startAt, _ := time.Parse("2006-01-02 15:04:05", request.StartAt)
	endAt, _ := time.Parse("2006-01-02 15:04:05", request.EndAt)
	return blog.CreateNotice(request.Title, request.Content, startAt, endAt)
}

type UpdateNoticeRequest struct {
	Title   string `json:"title"`
	StartAt string `json:"start_at"`
	EndAt   string `json:"end_at"`
	Content string `json:"content"`
}

func (request UpdateNoticeRequest) Do(id int) error {
	startAt, _ := time.Parse("2006-01-02 15:04:05", request.StartAt)
	endAt, _ := time.Parse("2006-01-02 15:04:05", request.EndAt)
	return blog.UpdateNotice(id, request.Title, request.Content, startAt, endAt)
}

type CarouselPaginatorRequest struct {
	Limit int `json:"limit"`
	Page  int `json:"page"`
}

func (request CarouselPaginatorRequest) Do() ([]blog.Carousel, int64, error) {
	return blog.GetCarouselPaginator(request.Limit, request.Page)
}

type CarouselEnableChangeRequest struct {
	Id     int  `json:"id"`
	Enable bool `json:"enable"`
}

func (request CarouselEnableChangeRequest) Do() error {
	return blog.ChangeCarouselEnable(request.Id, request.Enable)
}

type CarouseRemoveRequest struct {
	Id int `json:"id"`
}

func (request CarouseRemoveRequest) Do() error {
	return blog.RemoveCarouseById(request.Id)
}

type CarouselCreateRequest struct {
	Url     string `json:"url"`
	Href    string `json:"href"`
	StartAt string `json:"start_at"`
	EndAt   string `json:"end_at"`
}

func (request CarouselCreateRequest) Do() error {
	startAt, _ := time.Parse("2006-01-02", request.StartAt)
	endAt, _ := time.Parse("2006-01-02", request.EndAt)
	return blog.CreateCarousel(request.Url, request.Href, startAt, endAt, "")
}
